Skip to content
标签
工具
字数
536 字
阅读时间
3 分钟

一、应用场景

  • 动态引用配置外的java文件,编译后执行
  • 动态加载文件
  • web端编写代码,服务器编译执行返回结果

二、实现逻辑

java
package com.note.plan.dynamicCompiling;

import lombok.extern.slf4j.Slf4j;

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLClassLoader;

/**
 * @Classname TestDynamicCompiling
 * @Description 测试动态编译
 * @Date 2022/04/03 16:11
 * @Created by wxp
 */
@Slf4j
public class TestDynamicCompiling {

    public static void main(String[] args) throws IOException {
        //class所在文件夹
        String classpath = "E:\\IdeaWorkRoom\\note_project\\plan\\src\\main\\resources\\compiling\\";
        //文件名称
        String fileName = "TestCompilingClass";
        compileFile(classpath,fileName);
//        compileFile(classpath+fileName+".java");
//        runJavaClassByReflect(classpath,"compiling."+fileName);

    }
    /**
     * @Description: 编译java文件,默认为与源文件在同一个文件夹下
     * @param sourcePath 文件所在文件夹
     * @param sourceFile 文件名称
     * @return: void
     * @date: 2022/04/03
     */
    public static void compileFile(String sourcePath,String sourceFile) throws IOException {
        // 通过Runtime调用javac,启动新的进程去操作
        try {
            // 编码不一致可能会导致编译出错
            Process process = Runtime.getRuntime().exec("javac -encoding UTF-8 -cp " + sourcePath + " "+sourcePath+sourceFile+".java");
            InputStream errorStream = process.getErrorStream();
            InputStreamReader inputStreamReader = new InputStreamReader(errorStream, "gbk");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String line = null;
            while ((line=bufferedReader.readLine()) != null){
                System.out.println(line);
            }
            int exitVal = process.waitFor();
            System.out.println("Process exitValue: " + exitVal);
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    /**
     * @Description: 编译java文件,默认为与源文件在同一个文件夹下
     * @param sourceFile 
     * @return: int
     * @date: 2022/04/03
     */
    public static int compileFile(String sourceFile){
        //动态编译
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        //参数1:为java编译器提供参数
        //参数2:得到 Java 编译器的输出信息
        //参数3:接收编译器的 错误信息
        //参数4:可变参数(是一个String数组)能传入一个或多个 Java 源文件
        //返回值:0表示编译成功,非0表示编译失败
        int result = compiler.run(null, null, null,sourceFile);
        System.out.println(result==0?"编译成功":"编译失败");
        log.info(result==0?"编译成功":"编译失败");
        return result;
    }

    /**
     * @Description: 通过反射运行编译后的class
     * @param dir
     * @param classFile 如果有包名需添加包名,包名.类名
     * @return: void
     * @date: 2022/04/03
     */
    public static void runJavaClassByReflect(String dir,String classFile) {
        try {
            URL[] urls = new URL[] {new URL("file:/"+dir)};
            URLClassLoader loader = new URLClassLoader(urls);
            Class c = loader.loadClass(classFile);
            //调用加载类的main方法
            c.getMethod("main",String[].class).invoke(null, (Object)new String[]{});
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}